#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "cJSON.h"
#include "main.h"
#include "nvs_value.h"
#include "mqtt_event.h"
#include "mqtt_cjson_handle.h"
#include "radar.h"
#include "station.h"
#include "time_sntp.h"
#include "simple_ota.h"
#include "lamp_ctrl.h"
#include "ws2812.h"
#include "h03_config.h"

static const char* TAG = "[CJSON]";

static uint32_t mqtt_s = 1;
static uint8_t mqtt_error = 0;
static uint8_t set_server_flag = 0;
static char url_buf[256];
static char coreOtaUrl[128];
static bool force_report;
static bool mqtt_publish_state = 0;

void mqtt_publish_JSON(uint8_t cmd, cJSON *data)
{
    while(mqtt_publish_state == 1){
        vTaskDelay(50 / portTICK_PERIOD_MS);
    }
    if(mqtt_publish_state == 0){
        mqtt_publish_state = 1;

        int msg_id = 0;

        time_t system_time;
        time(&system_time);
        cJSON *root = cJSON_CreateObject();
        cJSON_AddNumberToObject(root, "cmd", cmd);
        cJSON_AddNumberToObject(root, "s", mqtt_s);
        cJSON_AddNumberToObject(root, "time", system_time);
        cJSON_AddStringToObject(root, "id", device_attr.device_mac);
        if(cmd != 102){
            cJSON_AddItemToObject(root,"data", data);
        }
        char *Json_data=cJSON_Print(root);
            if(device_attr.debug_mode == 2){
            cJSON *root2 = cJSON_Parse(Json_data);
            if(root2 != NULL){
                ESP_LOGD(TAG, "got cJSON");
                printf("%s\n",cJSON_Print(root2));
                cJSON_Delete(root2);
            }
        }

        if(cmd <= 103){
            msg_id = esp_mqtt_client_publish(client, MQTT_TOPIC_INFO, Json_data, strlen(Json_data), 0, 0);
        }else if(cmd == 104 || cmd == 110){
            msg_id = esp_mqtt_client_publish(client, MQTT_TOPIC_ATTR, Json_data, strlen(Json_data), 0, 0);
        }else if(cmd == 105){
            msg_id = esp_mqtt_client_publish(client, MQTT_TOPIC_EVENT, Json_data, strlen(Json_data), 0, 0);
        }else if(cmd == 106){
            msg_id = esp_mqtt_client_publish(client, MQTT_TOPIC_REPORT, Json_data, strlen(Json_data), 0, 0);
        }
        ESP_LOGD(TAG, "sent publish successful, msg_id=%d", msg_id);
        if(msg_id == -1){
            ESP_LOGE(TAG, "sent info ERROR!");
            mqtt_error++;
            if(mqtt_error == 10){
                ESP_LOGE(TAG, "MQTT_EVENT_RESET!");
                restart_os();
            }
            nvs_record_error(1, 11);
        }else{
            ESP_LOGD(TAG, "[%ld]sent %d successful!", mqtt_s, cmd);
            mqtt_error = 0;
            mqtt_s++;
            nvs_record_error(0, 11);
        }
        cJSON_free(Json_data);
        cJSON_Delete(root);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        // ESP_LOGI(TAG, "free heap size: %" PRIu32 " bytes", esp_get_free_heap_size());
        mqtt_publish_state = 0;
    }
}

void cJSON_creat_online(void)
{
        int8_t rssi = get_Wifi_RSSI();
        ESP_LOGI(TAG,"send online.");
        cJSON *data = cJSON_CreateObject();
        cJSON_AddStringToObject(data, "deviceType", DEVICE_MODEL);
        cJSON_AddNumberToObject(data, "rssi", rssi);

        mqtt_publish_JSON(100, data);
}

void cJSON_creat_sync(void)
{
    if(system_state.main == NORMAL){
        ESP_LOGI(TAG,"send system_sync.");
        cJSON *data = cJSON_CreateObject();
        cJSON_AddStringToObject(data, "deviceType", DEVICE_MODEL);
        cJSON_AddStringToObject(data, "softwareVersion", device_attr.software_version);
        cJSON_AddStringToObject(data, "hardwareVersion", device_attr.hardware_version);
        cJSON_AddStringToObject(data, "coreVersion", device_attr.radar_version);

        mqtt_publish_JSON(101, data);
    }
}

void cJSON_creat_heartbeat(void)
{
    if(system_state.main == NORMAL){
        ESP_LOGI(TAG,"send heartbeat.");
        mqtt_publish_JSON(102, 0);
    }
}

void cJSON_creat_error(uint16_t code)
{
    if(system_state.main == NORMAL || system_state.main == OTA){
        int8_t rssi = get_Wifi_RSSI();
        cJSON *data = cJSON_CreateObject();
        cJSON_AddStringToObject(data, "deviceType", DEVICE_MODEL);
        cJSON_AddStringToObject(data, "softwareVersion", device_attr.software_version);
        cJSON_AddStringToObject(data, "hardwareVersion", device_attr.hardware_version);
        cJSON_AddStringToObject(data, "coreVersion", device_attr.radar_version);
        cJSON_AddNumberToObject(data, "rssi", rssi);
        cJSON_AddNumberToObject(data, "now", system_state.error_now);
        cJSON_AddNumberToObject(data, "history", system_state.error_ex);
        cJSON_AddNumberToObject(data, "errorCode", code);

        mqtt_publish_JSON(103, data);
    }
}

void cJSON_creat_attr(char *item, int value)
{
    if(system_state.main == NORMAL){
        ESP_LOGI(TAG,"send attr %s: [%d].", item, value);
        cJSON *data = cJSON_CreateObject();
        cJSON *array = NULL;
        if(strcmp(item, "all") == 0){
            cJSON_AddNumberToObject(data, "onoff_status", lamp.onoff_status);
            cJSON_AddNumberToObject(data, "control_mode", lamp.control_mode);
            cJSON_AddNumberToObject(data, "brightness_val", lamp.brightness_val);
            cJSON_AddNumberToObject(data, "color_temp", lamp.color_temp);
            cJSON_AddNumberToObject(data, "delay_time", lamp.delay_time);
            cJSON_AddNumberToObject(data, "gesture_mode", user_attr.gesture_mode);
            array = cJSON_CreateArray();

            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.mild));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.moderate));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.severe));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.lighting));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.present));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.now));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.sum));
            cJSON_AddItemToObject(data, "study_time", array);
        }else if(strcmp(item, "study_time") == 0){
            array = cJSON_CreateArray();
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.mild));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.moderate));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.severe));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.lighting));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.present));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.now));
            cJSON_AddItemToArray(array, cJSON_CreateNumber(learning_duration.sum));
            cJSON_AddItemToObject(data, "study_time", array);
        }else{
            cJSON_AddNumberToObject(data, item, value);
        }
        mqtt_publish_JSON(104, data);
    }
}

void cJSON_creat_event(char *item, int value)
{
    if(system_state.main == NORMAL){
        ESP_LOGI(TAG,"send event %s: [%d].", item, value);
        cJSON *data = cJSON_CreateObject();
        cJSON_AddNumberToObject(data, item, value);
        mqtt_publish_JSON(105, data);
    }
}

void cJSON_creat_report(report_attr_t report, cJSON *data)
{
    if(report.ss_time != user_attr.rpt_start || force_report == 1){
                    force_report = 0;
                    ESP_LOGI(TAG,"send learning report.");
        user_attr.rpt_start = report.ss_time;
        // vTaskDelay(200 / portTICK_PERIOD_MS);
        if(system_state.main == NORMAL){
            mqtt_publish_JSON(106, data);
                    }
        paramenter_setting_u32("rpt_start", user_attr.rpt_start);
                }else{
                    ESP_LOGI(TAG, "The report is not the lastest.");
                    cJSON_Delete(data);
                }
}

void cJSON_creat_raw(void)
{
    if(system_state.main == NORMAL){
        ESP_LOGD(TAG,"send event raw.");
        cJSON *data = cJSON_CreateObject();
        cJSON *array = cJSON_CreateArray();
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.body_status));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.body_movement));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.respiratory));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.flow_state));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.posture_state));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.activity_freq));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.body_distance));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.body_angle));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.head_pos));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.head_angle));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.hand_pos));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.hand_angle));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.heart_rate));
        cJSON_AddItemToArray(array, cJSON_CreateNumber(human_state.position_interval));
        cJSON_AddItemToObject(data, "raw", array);

        mqtt_publish_JSON(110, data);
    }
}

static void user_ota_task(void *parm)
{
    ESP_LOGI(TAG, "OTA task START.");
    system_state.main = OTA;
    uint8_t top_led_state_bak = top_led_mode;
    if(device_attr.silent_ota == 0) {
        top_led_mode = 1;
        event_flag.led_break = 1;
    }
    if(system_state.base_ota == 1){
        ESP_LOGI(TAG, "base OTA start");
        cJSON_creat_error(1202);
        //调用函数进行升级
        esp_err_t ret = simple_ota_func(url_buf);
        nvs_record_error(ret, 12);
        if(ret == ESP_OK){
            cJSON_creat_error(1200);
            if(device_attr.silent_ota == 0) {
                led_notify = BLUE_NOTIFICATION;
                event_flag.led_break = 1;
            }else{
                paramenter_setting_u8("onoff_status", lamp.onoff_status);
            }
            system_state.main = BOOTING;
            ESP_LOGI(TAG, "base OTA succeed,ready restart!");
            restart_os();
        }else{
            cJSON_creat_error(1201);
            if(device_attr.silent_ota == 0) {
                led_notify = RED_NOTIFICATION;
                event_flag.led_break = 1;
            }
            ESP_LOGE(TAG, "Firmware Upgrades Failed");
        }
        system_state.base_ota = 0;
    }
    if(device_attr.silent_ota == 0) {
        top_led_mode = top_led_state_bak;
        event_flag.led_break = 1;
    }     
    system_state.main = NORMAL;
    ESP_LOGI(TAG, "OTA task finish");
    vTaskDelete(NULL);
}

void mqtt_data_parse(char *topic, char *rawdata)
{
	cJSON *root = NULL;
    int cmd = 0;
    time_t mqttTime = 0;
    char *id = NULL;
    cJSON *data = NULL;
    cJSON *tempData = NULL;
	time_t system_time;
	time(&system_time);
    bool lamp_updata_flag = 0;
    uint8_t cmd_type = 0;

	if(topic == NULL){
		ESP_LOGE(TAG, "topic is NULL, invalide data");
	}else{
        if(strstr(topic, "ctrl") != NULL){
            cmd_type = 1;
            ESP_LOGI(TAG, "MQTT set control");
        }else if(strstr(topic, "func") != NULL){
            cmd_type = 2;
            ESP_LOGI(TAG, "MQTT set function");
        }
		root = cJSON_Parse(rawdata);
		if(root != NULL){
            if(device_attr.debug_mode == 2){
                ESP_LOGD(TAG, "got cJSON");
                printf("%s\n",cJSON_Print(root));
                char *Json_data;
                Json_data = cJSON_Print(root);
                printf("%s\n", Json_data);
                cJSON_free(Json_data);
            }
            tempData = cJSON_GetObjectItem(root, "cmd");
            if(tempData != NULL && cJSON_IsNumber(tempData)){
                cmd = tempData->valueint;
                ESP_LOGI(TAG, "cmd:%d", cmd);
                if((cmd_type == 1 && cmd > 204) || (cmd_type == 2 && cmd < 205)){
                    ESP_LOGE(TAG, "wrong cmd!!!");
                    goto clean;
                }
            }
            tempData = cJSON_GetObjectItem(root, "s");
            if(tempData != NULL && cJSON_IsNumber(tempData)){
                uint32_t sync_s = tempData->valueint;
                ESP_LOGI(TAG, "s:%ld", sync_s);
            }
            if(cmd == 201){
                tempData = cJSON_GetObjectItem(root, "time");
                if(tempData != NULL && cJSON_IsNumber(tempData)){
                    mqttTime = tempData->valueint;
                    ESP_LOGI(TAG, "time:%lld", mqttTime);
                    ESP_LOGI(TAG, "Notification of a time synchronization event");
                    
                    struct timeval tv = {mqttTime, 0};
                                        
                    settimeofday(&tv, NULL);
                    time_update(mqttTime);
                }
            }

            tempData = cJSON_GetObjectItem(root, "id");
            if(tempData != NULL && cJSON_IsString(tempData)){
                id = tempData->valuestring;
                ESP_LOGI(TAG, "id:%s", id);
                if (memcmp(id, device_attr.device_mac, strlen(id)) != 0) {
                    ESP_LOGE(TAG, "mqtt down mac error: %s", id);
                    goto clean;
                }
            }

			data = cJSON_GetObjectItem(root, "data");
			if (data != NULL) {
                if(cmd == 201 && device_attr.debug_mode != 7){
                    tempData = cJSON_GetObjectItem(data, "upgrade");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t upgrade = tempData->valueint;
                        if(upgrade == 1 || device_attr.force_upgrade == 1){
                            device_attr.force_upgrade = 0;
                            ESP_LOGI(TAG, "run upgrade");
                            tempData = cJSON_GetObjectItem(data, "silent");
                            if(tempData != NULL && cJSON_IsNumber(tempData)){
                                device_attr.silent_ota = tempData->valueint;
                                ESP_LOGI(TAG, "silent_ota:%d", device_attr.silent_ota);
                                if(device_attr.silent_ota == 1){
                                    paramenter_setting_u8("s_ota", device_attr.silent_ota);
                                }
                            }
                            tempData = cJSON_GetObjectItem(data, "remoteCoreVersion");
                            if(tempData != NULL && cJSON_IsString(tempData)){
                                char *remoteCoreVersion = tempData->valuestring;
                                ESP_LOGI(TAG, "Core_Version:%s", remoteCoreVersion);
                                if(strcmp(remoteCoreVersion, device_attr.radar_version) != 0){
                                    tempData = cJSON_GetObjectItem(data, "coreOtaUrl");
                                    if(tempData != NULL && cJSON_IsString(tempData)){
                                        memcpy(coreOtaUrl, tempData->valuestring, sizeof(coreOtaUrl));
                                        ESP_LOGI(TAG, "coreOtaUrl:%s", coreOtaUrl);
                                        if(strstr(coreOtaUrl,"http") != NULL){
                                            system_state.radar_ota = 1;
                                        }else{
                                            nvs_record_error(1, 13);
                                            cJSON_creat_error(1304);
                                            ESP_LOGE(TAG, "wrong core url");
                                        }
                                    }
                                }else{
                                    nvs_record_error(0, 13);
                                    cJSON_creat_error(1303);
                                    ESP_LOGI(TAG, "radar_version is already the lastest version");
                                }
                            }
                            tempData = cJSON_GetObjectItem(data, "remoteBaseVersion");
                            if(tempData != NULL && cJSON_IsString(tempData)){
                                char *remoteBaseVersion = tempData->valuestring;
                                ESP_LOGI(TAG, "Base_Version:%s", remoteBaseVersion);
                                if(strcmp(remoteBaseVersion, device_attr.software_version) != 0){
                                    tempData = cJSON_GetObjectItem(data, "baseOtaUrl");
                                    if(tempData != NULL && cJSON_IsString(tempData)){
                                        char *baseOtaUrl = tempData->valuestring;
                                        strcpy(url_buf, baseOtaUrl);
                                        ESP_LOGI(TAG, "baseOtaUrl:%s", url_buf);
                                        if(strstr(baseOtaUrl,"http") != NULL){
                                            system_state.base_ota = 1;
                                        }else{
                                            nvs_record_error(1, 12);
                                            cJSON_creat_error(1204);
                                            ESP_LOGE(TAG, "wrong base url");
                                        }
                                    }
                                }else{
                                    nvs_record_error(0, 12);
                                    cJSON_creat_error(1203);
                                    ESP_LOGI(TAG, "base_version is already the lastest version");
                                }
                            }
                            if(system_state.main == NORMAL){
                                if(system_state.base_ota == 1 || system_state.radar_ota == 1){
                                    xTaskCreate(user_ota_task, "user_ota_task", 1024*4, NULL, 16, NULL);
                                }
                            }
                        }
                    }
                }else if(cmd == 203){
                    tempData = cJSON_GetObjectItem(data, "restore");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t restore = tempData->valueint;
                        ESP_LOGI(TAG, "restore:%d", restore);
                        if(restore <= 4){
                            paramenter_restore(restore);
                            cJSON_creat_error(0);
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "rst_delay");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        timer_count.rst_delay = tempData->valueint+1;
                        ESP_LOGI(TAG, "rst_delay:%d", timer_count.rst_delay);
                        cJSON_creat_error(0);
                    }
                    tempData = cJSON_GetObjectItem(data, "debug_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        device_attr.debug_mode = tempData->valueint;
                        ESP_LOGI(TAG, "debug_mode:%d", device_attr.debug_mode);
                        paramenter_setting_u8("debug_mode", device_attr.debug_mode);
                        if(device_attr.debug_mode == 0){
                            esp_log_level_set("*", ESP_LOG_ERROR);
                        }else if(device_attr.debug_mode == 1){
                            esp_log_level_set("*", ESP_LOG_INFO);
                        }else if(device_attr.debug_mode == 2){
                            esp_log_level_set("*", ESP_LOG_DEBUG);
                        }
                        cJSON_creat_error(0);
                    }
                    tempData = cJSON_GetObjectItem(data, "demo_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        device_attr.demo_mode = tempData->valueint;
                        ESP_LOGI(TAG, "demo_mode:%d", device_attr.demo_mode);
                        paramenter_setting_u8("demo_mode", device_attr.demo_mode);
                        if(device_attr.demo_mode == 7){
                            event_flag.led_break = 1;
                        }else if(device_attr.demo_mode == 1){
                            esp_log_level_set("*", ESP_LOG_NONE);
                        }else{
                            if(device_attr.debug_mode == 2){
                                esp_log_level_set("*", ESP_LOG_DEBUG);
                            }else if(device_attr.debug_mode == 1){
                                esp_log_level_set("*", ESP_LOG_INFO);
                            }else if(device_attr.debug_mode == 0){
                                esp_log_level_set("*", ESP_LOG_ERROR);
                            }
                        }
                        cJSON_creat_error(0);
                    }
                    tempData = cJSON_GetObjectItem(data, "mac");
                    if(tempData != NULL && cJSON_IsString(tempData)){
                        char mac[18];
                        strcpy(mac, tempData->valuestring);
                        ESP_LOGI(TAG, "bt_mac:%s", mac);
                        paramenter_setting_str("bt_mac", mac);
                        cJSON_creat_error(0);
                    }
                    tempData = cJSON_GetObjectItem(data, "errorCode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t code = tempData->valueint;
                        ESP_LOGI(TAG, "errorCode:%d", code);
                        if(code == 1){
                            cJSON_creat_error(0);
                            paramenter_setting_str("error", "0");
                            system_state.error_ex = 0;
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "touch_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        user_attr.touch_mode = tempData->valueint;
                        ESP_LOGI(TAG, "touch_mode:%d", user_attr.touch_mode);
                        paramenter_setting_u8("touch_mode", user_attr.touch_mode);
                        cJSON_creat_error(0);
                        restart_os();
                    }
                    tempData = cJSON_GetObjectItem(data, "server");
                    if(tempData != NULL){
                        cJSON *serverData = NULL;
                        serverData = cJSON_GetObjectItem(tempData, "brokenurl");
                        if(serverData != NULL && cJSON_IsString(serverData)){
                            char *server_buf = serverData->valuestring;
                            if(strlen(server_buf) != 0 && strstr(server_buf,"mqtt://") != NULL){
                                set_server_flag |= 1;
                                ESP_LOGI(TAG, "[%d]broken url: %s", set_server_flag, server_buf);
                                paramenter_setting_str("brokerurluser",server_buf);
                            }else{
                                ESP_LOGE(TAG, "broken url error!");
                                led_notify = RED_NOTIFICATION;
                                event_flag.led_break = 1;
                            }
                        }
                        serverData = cJSON_GetObjectItem(tempData, "account");
                        if(serverData != NULL && cJSON_IsString(serverData)){
                            char *server_buf = serverData->valuestring;
                            if(strlen(server_buf) != 0){
                                set_server_flag |= 1<<1;
                                ESP_LOGI(TAG, "[%d]broken accesskey: %s", set_server_flag, server_buf);
                                paramenter_setting_str("acckeyuser",server_buf);
                            }else{
                                ESP_LOGE(TAG, "accesskey error!");
                                led_notify = RED_NOTIFICATION;
                                event_flag.led_break = 1;
                            }
                        }
                        serverData = cJSON_GetObjectItem(tempData, "passwd");
                        if(serverData != NULL && cJSON_IsString(serverData)){
                            char *server_buf = serverData->valuestring;
                            if(strlen(server_buf) != 0){
                                set_server_flag |= 1<<2;
                                ESP_LOGI(TAG, "[%d]broken secretkey: %s", set_server_flag, server_buf);
                                paramenter_setting_str("secretkeyuser",server_buf);	
                            }else{
                                ESP_LOGE(TAG, "secretkey error!");
                                led_notify = RED_NOTIFICATION;
                                event_flag.led_break = 1;
                            }
                        }
                        serverData = cJSON_GetObjectItem(tempData, "decode");
                        if(serverData != NULL && cJSON_IsNumber(serverData)){
                            uint8_t decode = serverData->valueint;
                            set_server_flag |= 1<<3;
                            ESP_LOGI(TAG, "[%d]decode: %d", set_server_flag, decode);
                            paramenter_setting_u8("decode", decode);
                        }
                        serverData = cJSON_GetObjectItem(tempData, "clientId");
                        if(serverData != NULL && cJSON_IsString(serverData)){
                            char *server_buf = serverData->valuestring;
                            if(strlen(server_buf) != 0){
                                set_server_flag |= 1<<4;
                                ESP_LOGI(TAG, "[%d]broken groupid: %s", set_server_flag, server_buf);
                            }else{
                                ESP_LOGE(TAG, "groupid error!");
                                led_notify = RED_NOTIFICATION;
                                event_flag.led_break = 1;
                            }
                        }
                        serverData = cJSON_GetObjectItem(tempData, "mqttver");
                        if(serverData != NULL && cJSON_IsString(serverData)){
                            char *server_buf = serverData->valuestring;
                            if(strlen(server_buf) != 0){
                                set_server_flag |= 1<<5;
                                ESP_LOGI(TAG, "[%d]mqtt ver: %s", set_server_flag, server_buf);
                                if(strcmp(server_buf,"3.1") == 0){
                                    paramenter_setting_u8("mqttveruser",1);
                                }else if(strcmp(server_buf,"3.1.1") == 0){
                                    paramenter_setting_u8("mqttveruser",2);
                                }else{
                                    paramenter_setting_u8("mqttveruser",0);
                                }
                            }else{
                                ESP_LOGE(TAG, "mqttver error!");
                                led_notify = RED_NOTIFICATION;
                                event_flag.led_break = 1;
                            }
                        }
                        uint8_t mqtt_item = set_server_flag & 0x07;
                        ESP_LOGI(TAG, "set_server_flag: %d, mqtt_item: %d", set_server_flag, mqtt_item);
                        if(mqtt_item == 7){
                            mqtt_item = (set_server_flag >> 3)&0x01;
                            if(mqtt_item == 0){
                                ESP_LOGI(TAG, "decode is empty , set 0");
                                paramenter_setting_u8("decode", 0);
                            }
                            mqtt_item = (set_server_flag >> 4)&0x01;
                            if(mqtt_item == 0){
                                ESP_LOGI(TAG, "Group ID is empty , set GID_DEV_MQTT");
                                paramenter_setting_str("groupiduser","GID_DEV_MQTT");
                            }
                            mqtt_item = (set_server_flag >> 5)&0x01;
                            if(mqtt_item == 0){
                                ESP_LOGI(TAG, "mqtt version is empty , set mqttver 5.0");
                                paramenter_setting_u8("mqttver", 0);
                            }
                            ESP_LOGI(TAG, "new broker param set done , ready reset!");
                            led_notify = BLUE_NOTIFICATION;
                            event_flag.led_break = 1;
                            paramenter_setting_u8("newuser", 1);
                            paramenter_setting_u8("mqttwork", 0);
                            set_server_flag = 0;
                            restart_os();
                        }else{
                            ESP_LOGE(TAG, "missing set_server parameter, set_server failed!");
                            set_server_flag = 0;
                            led_notify = RED_NOTIFICATION;
                            event_flag.led_break = 1;
                        }
                    }
                }else if(cmd == 204){
                    tempData = cJSON_GetObjectItem(data, "attr");
                    if(tempData != NULL && cJSON_IsString(tempData)){
                        char *attr = tempData->valuestring;
                        ESP_LOGI(TAG, "attr:%s", attr);
                        if(strcmp(attr, "all") == 0){
                            event_flag.all_attr = 1;
                        }
                        if(strcmp(attr, "respiratory") == 0){
                            event_flag.respiratory = 1;
                        }
                        if(strcmp(attr, "heart_rate") == 0){
                            event_flag.heart_rate = 1;
                        }
                        if(strcmp(attr, "body_movement") == 0){
                            event_flag.body_movement = 1;
                        }
                        if(strcmp(attr, "body_angle") == 0){
                            event_flag.body_angle = 1;
                        }
                        if(strcmp(attr, "body_distance") == 0){
                            event_flag.body_distance = 1;
                        }
                        if(strcmp(attr, "flow_state") == 0){
                            event_flag.flow_state = 1;
                        }
                        if(strcmp(attr, "position_interval") == 0){
                            event_flag.position_interval = 1;
                        }
                        if(strcmp(attr, "onoff_status") == 0){
                           cJSON_creat_attr("onoff_status", lamp.onoff_status);
                        }
                        if(strcmp(attr, "control_mode") == 0){
                            cJSON_creat_attr("control_mode", lamp.control_mode);
                        }
                        if(strcmp(attr, "brightness_val") == 0){
                           cJSON_creat_attr("brightness_val", lamp.brightness_val);
                        }
                        if(strcmp(attr, "color_temp") == 0){
                           cJSON_creat_attr("color_temp", lamp.color_temp);
                        }
                        if(strcmp(attr, "delay_time") == 0){
                           cJSON_creat_attr("delay_time", lamp.delay_time);
                        }
                        if(strcmp(attr, "study_time") == 0){
                            event_flag.study_time = 1;
                        }
                        if(strcmp(attr, "gesture_mode") == 0){
                            event_flag.gesture_mode = 1;
                        }
                        if(strcmp(attr, "report") == 0){
                            force_report = 1;
                            event_flag.report = 1;
                        }
                    }
                }else if(cmd == 205){
                    tempData = cJSON_GetObjectItem(data, "set_working_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t set_working_mode = tempData->valueint;
                        if(user_attr.working_mode != set_working_mode){
                            user_attr.working_mode = set_working_mode;
                            cJSON_creat_attr("working_mode", user_attr.working_mode);
                            paramenter_setting_u8("working_mode", user_attr.working_mode);
                            ESP_LOGI(TAG, "set_working_mode:%d", set_working_mode);
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "set_sending_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t set_sending_mode = tempData->valueint;
                        if(user_attr.sending_mode != set_sending_mode){
                            user_attr.sending_mode = set_sending_mode;
                            cJSON_creat_attr("sending_mode", user_attr.sending_mode);
                            paramenter_setting_u8("sending_mode", user_attr.sending_mode);
                            ESP_LOGI(TAG, "set_sending_mode:%d", set_sending_mode);
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "set_sending_period");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint16_t set_sending_period = tempData->valueint;
                        if(user_attr.sending_period != set_sending_period){
                            user_attr.sending_period = set_sending_period;
                            cJSON_creat_attr("sending_period", user_attr.sending_period);
                            paramenter_setting_u8("sending_period", user_attr.sending_period);
                            ESP_LOGI(TAG, "set_sending_period:%d", set_sending_period);
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "set_onoff_status");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t set_onoff_status = tempData->valueint;
                        ESP_LOGI(TAG, "set_onoff_status:%" PRIu8 "", set_onoff_status);
                        if(set_onoff_status <= 1){
                            if(lamp.onoff_status != set_onoff_status){
                                lamp.onoff_status = set_onoff_status;
                                lamp_updata_flag = 1;
                            }
                        }
                    }
                    if(lamp.onoff_status == 1){
                        tempData = cJSON_GetObjectItem(data, "set_brightness_val");
                        if(tempData != NULL && cJSON_IsNumber(tempData)){
                            uint8_t set_brightness_val = tempData->valueint;
                            ESP_LOGI(TAG, "set_brightness_val:%" PRIu8 "", set_brightness_val);
                            if(set_brightness_val == 0){
                                set_brightness_val = 1;
                            }
                            if(lamp.brightness_val != set_brightness_val){
                                lamp.brightness_val = set_brightness_val;
                                cJSON_creat_attr("brightness_val", lamp.brightness_val);
                                lamp_updata_flag = 1;
                            }
                        }
                        tempData = cJSON_GetObjectItem(data, "set_color_temp");
                        if(tempData != NULL && cJSON_IsNumber(tempData)){
                            uint8_t set_color_temp = tempData->valueint;
                            ESP_LOGI(TAG, "set_color_temp:%" PRIu8 "", set_color_temp);
                            if(lamp.color_temp != set_color_temp){
                                lamp.color_temp = set_color_temp;
                                cJSON_creat_attr("color_temp", lamp.color_temp);
                                paramenter_setting_u8("color_temp", lamp.color_temp);
                                lamp_updata_flag = 1;
                            }
                        }
                    }
                    if(lamp_updata_flag == 1){
                        lamp_updata(lamp.onoff_status, lamp.brightness_val, lamp.color_temp);
                    }
                    tempData = cJSON_GetObjectItem(data, "set_control_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t set_control_mode = tempData->valueint;
                        ESP_LOGI(TAG, "set_control_mode:%" PRIu8 "", set_control_mode);
                        if(set_control_mode <= 1){
                            if(lamp.control_mode != set_control_mode){
                                lamp.control_mode = set_control_mode;
                                cJSON_creat_attr("control_mode", lamp.control_mode);
                                paramenter_setting_u8("control_mode", lamp.control_mode);
                            }
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "set_delay_time");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                        uint8_t set_delay_time = tempData->valueint;
                        ESP_LOGI(TAG, "set_delay_time:%" PRIu8 "", set_delay_time);
                        if(lamp.delay_time != set_delay_time){
                            lamp.delay_time = set_delay_time;
                            cJSON_creat_attr("delay_time", lamp.delay_time);
                            paramenter_setting_u16("delay_time", lamp.delay_time);
                        }
                    }
                    tempData = cJSON_GetObjectItem(data, "set_gesture_mode");
                    if(tempData != NULL && cJSON_IsNumber(tempData)){
                            uint8_t set_gesture_mode = tempData->valueint;
                        if(user_attr.gesture_mode != set_gesture_mode){
                            user_attr.gesture_mode = set_gesture_mode;
                            cJSON_creat_attr("gesture_mode", user_attr.gesture_mode);
                            paramenter_setting_u8("gesture_mode", user_attr.gesture_mode);
                            ESP_LOGI(TAG, "set_gesture_mode:%d", set_gesture_mode);
                        }
                    }
                }
			}
		}else{
			ESP_LOGE(TAG, "invalide Json data");
		}
        clean:
        cJSON_Delete(root);
	}
    // ESP_LOGI(TAG, "free heap size: %" PRIu32 " bytes", esp_get_free_heap_size());
}